/**
 * @file read.c
 * @brief 实现一个简单的电子书阅读器
 * @details 该文件包含文本显示、翻页、切换章节等功能。它依赖于触摸屏进行交互，
 * 并使用 HZK16 和 ASC16 字体库来渲染中英文字符。
 * @version 1.0
 * @date 2025-07-05
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ASC16.h"
#include "HZK16.h"
#include "read.h" // 假设 read.h 中包含了 show_page 和 show_txt 的声明
#include "lcd.h"
#include "ts.h"

/// @brief 存储小说章节文件名的全局数组
const char* chapters[] =
{
    "1.txt","2.txt","3.txt","4.txt","5.txt","6.txt",
    "7.txt","8.txt","9.txt","10.txt","11.txt","12.txt",
    "13.txt","14.txt","15.txt","16.txt","17.txt","18.txt",
};

/**
 * @brief 显示指定文本文件，并处理用户交互（翻页、换章）
 * @details 此函数是电子书阅读器的主循环。它打开一个文本文件，
 * 通过触摸屏获取用户输入，并根据触摸位置执行上一页/下一页、
 * 上一章/下一章的操作。
 * @param filename 要打开的初始章节文件名 (例如 "1.txt")
 */
void show_txt(char *filename, int fd_ts)
{
    long page_positions[100] = {0};
    int current_page = 0;
    int current_chapter = 0;

    struct postion pos;
    int ret;

    // 查找当前文件在 chapters 数组中的索引
    for (int i = 0; i < sizeof(chapters) / sizeof(chapters[0]); i++)
    {
        if (strcmp(filename, chapters[i]) == 0)
        {
            current_chapter = i;
            break;
        }
    }

    // 构造初始文件路径
    char initial_filepath[256]; // 确保缓冲区足够大
    snprintf(initial_filepath, sizeof(initial_filepath), "./res/novel/%s", filename);

    // 1. 打开指定文件
    FILE *fp = fopen(initial_filepath, "r");
    if (fp == NULL)
    {
        perror("fopen initial_filepath"); // 更好的错误提示
        return;
    }

    page_positions[0] = ftell(fp);
    show_page(fp); // 显示第一页

    while (1)
    {
        pos = ts_xy(fd_ts);

        // 上一页
        if (pos.x > 640 && (pos.y > 0) && (pos.y < 95))
        {
            if (current_page > 0)
            {
                current_page--;
                fseek(fp, page_positions[current_page], SEEK_SET); // 定位到上一页的开始位置
                brush_lcd(0xffffff);
                // 修正 draw_bmp 参数顺序
                draw_bmp("./res/imagefiles/change.bmp", 640, 0); // Corrected argument order
                // 重新显示上一页
                show_page(fp);
            }
        }
        // 下一页
        if (pos.x > 640 && (pos.y > 95) && (pos.y < 190))
        {
            page_positions[current_page + 1] = ftell(fp);
            brush_lcd(0xffffff);
            // 修正 draw_bmp 参数顺序
            draw_bmp("./res/imagefiles/change.bmp", 640, 0); // Corrected argument order
            ret = show_page(fp);
            if (ret == -1)
            {
                printf("%s is over\n", filename);
                rewind(fp);
                current_page = 0;
                page_positions[0] = ftell(fp);
                brush_lcd(0xffffff);
                // 修正 draw_bmp 参数顺序
                draw_bmp("./res/imagefiles/change.bmp", 640, 0); // Corrected argument order
                show_page(fp);
            }
            else
            {
                current_page++;
            }
        }
        // 上一章
        if (pos.x > 640 && (pos.y > 190) && (pos.y < 285))
        {
            if (current_chapter > 0)
            {
                current_chapter--;
                fclose(fp); // 关闭当前文件

                // 构造新章节的文件路径
                char chapter_path[256]; // 确保缓冲区足够大
                snprintf(chapter_path, sizeof(chapter_path), "./res/novel/%s", chapters[current_chapter]);
                fp = fopen(chapter_path, "r"); // 打开上一章
                if (fp == NULL)
                {
                    perror("fopen previous chapter"); // 更好的错误提示
                    return;
                }
                current_page = 0;
                page_positions[0] = ftell(fp);
                brush_lcd(0xffffff);
                // 修正 draw_bmp 参数顺序
                draw_bmp("./res/imagefiles/change.bmp", 640, 0); // Corrected argument order
                show_page(fp);
            }
        }
        // 下一章
        if (pos.x > 640 && (pos.y > 285) && (pos.y < 380))
        {
            if (current_chapter < sizeof(chapters) / sizeof(chapters[0]) - 1)
            {
                current_chapter++;
                fclose(fp); // 关闭当前文件

                // 构造新章节的文件路径
                char chapter_path[256]; // 确保缓冲区足够大
                snprintf(chapter_path, sizeof(chapter_path), "./res/novel/%s", chapters[current_chapter]);
                fp = fopen(chapter_path, "r"); // 打开下一章
                if (fp == NULL)
                {
                    perror("fopen next chapter"); // 更好的错误提示
                    return;
                }
                current_page = 0;
                page_positions[0] = ftell(fp);
                brush_lcd(0xffffff);
                // 修正 draw_bmp 参数顺序
                draw_bmp("./res/imagefiles/change.bmp", 640, 0); // Corrected argument order
                show_page(fp);
            }
        }
    }
}

/**
 * @brief 从文件中读取并显示一页内容（最多30行）
 * @details 该函数从文件指针当前位置开始读取数据，逐行解析。
 * 它能够识别 ASCII 字符和 GB2312 编码的汉字，并调用相应的
 * 绘图函数将它们渲染到屏幕上。
 * @param fp  指向已打开文件的指针，该指针指向要显示的页面内容的起始位置
 * @return int 成功显示一页返回0，如果到达文件末尾或发生读取错误则返回-1
 */
int show_page(FILE *fp)
{
    // 读取30行
    int i, j;
    char *p;
    unsigned char buf[81]; // 确保缓冲区足够处理一行数据 + null 终止符
    int qu, wei;

    for (j = 0; j < 30; j++)
    {
        p = fgets(buf, sizeof(buf), fp); // 使用 sizeof(buf) 避免溢出
        if (p == NULL)
        {
            return -1; // 文件结束或读取错误
        }

        // printf("buf=%s\n", buf); // 调试语句，可以注释掉

        // 逐字符解析并显示
        for (i = 0; i < strlen(buf);)
        {
            if (buf[i] < 128) // ASCII 字符
            {
                draw_8x16(0 + i * 8, j * 16, &szASC16[buf[i] * 16], 0xff);
                i++;
            }
            else // 汉字（GB2312 编码通常占 2 字节）
            {
                if (i + 1 < strlen(buf)) // 确保有足够的字节构成一个汉字
                {
                    qu = buf[i] - 161;   // 区码
                    wei = buf[i + 1] - 161; // 位码
                    
                    if (qu >= 0 && qu < 94 && wei >= 0 && wei < 94) // 更精确的GB2312范围检查
                    {
                        draw_16x16(0 + i * 8, j * 16, &szHZK16[32 * (qu * 94 + wei)], 0xff);
                    }
                    else
                    {
                        // 非法汉字编码，显示 'xx'
                        draw_8x16(0 + i * 8, j * 16, &szASC16['x' * 16], 0xff);
                        draw_8x16(0 + (i + 1) * 8, j * 16, &szASC16['x' * 16], 0xff);
                    }
                }
                else
                {
                    // 字节不足以构成一个完整汉字，显示 'xx'
                    draw_8x16(0 + i * 8, j * 16, &szASC16['x' * 16], 0xff);
                    // i+1 可能会超出buf范围，但这里只是显示，没有访问，所以问题不大，但更好是只画一个'x'或跳过
                }
                i += 2; // 处理完一个汉字（2字节）
            }
        }
    }
    return 0; // 成功显示一页
}